package com.diligent.cloud.sfc.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.canny.commons.model.Codes;
import com.canny.commons.model.ListResult;
import com.canny.commons.model.ObjectResult;
import com.canny.commons.model.Result;
import com.canny.commons.page.IPage;
import com.canny.commons.page.Pagination;
import com.codingapi.txlcn.tc.annotation.LcnTransaction;
import com.diligent.cloud.identity.service.IBusinessNumberControllerFeign;
import com.diligent.cloud.identity.service.IdentityService;
import com.diligent.cloud.logistics.container.model.LcmBoxFillDetail;
import com.diligent.cloud.logistics.container.service.LcmBoxFillDetailFeignService;
import com.diligent.cloud.primary.data.feign.service.imat.IMatImageFeignService;
import com.diligent.cloud.prodbatch.model.MfgProdBatch;
import com.diligent.cloud.prodbatch.service.MfgProdBatchFeignService;
import com.diligent.cloud.sfc.config.OauthConfig;
import com.diligent.cloud.sfc.factory.StationFactory;
import com.diligent.cloud.sfc.factory.impl.*;
import com.diligent.cloud.sfc.model.OrderType;
import com.diligent.cloud.sfc.model.StationType;
import com.diligent.cloud.sfc.model.enums.MatStatus;
import com.diligent.cloud.sfc.model.info.OrderInfo;
import com.diligent.cloud.sfc.model.params.OrderListParams;
import com.diligent.cloud.sfc.service.ISfcService;
import com.diligent.cloud.sfc.service.WoOrderService;
import com.diligent.cloud.sfc.service.WorkShopPostProcessService;
import com.diligent.cloud.sfc.util.ConverterUtil;
import com.diligent.cloud.web.model.PageAndCondition;
import com.diligent.cloud.workorder.enums.WoOrderStatus;
import com.diligent.cloud.workorder.model.WoOperationCompleteDetail;
import com.diligent.cloud.workorder.model.WoOrder;
import com.diligent.cloud.workorder.model.WoOrderLot;
import com.diligent.cloud.workorder.model.WoOrderProgressParams;
import com.diligent.cloud.workorder.service.WoOperationCompleteDetailFeignService;
import com.diligent.cloud.workorder.service.WoOrderFeignService;
import com.diligent.cloud.workorder.service.WoOrderLotFeignService;
import com.diligent.cloud.workordermd.feign.service.MfgMdApplyUseFeignService;
import com.diligent.cloud.workordermd.model.MfgMdApplyUse;
import com.diligent.foundation.data.model.v2.Condition;
import com.google.common.base.Preconditions;
import org.springframework.beans.BeanUtils;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.security.Principal;
import java.util.*;

/**
 * WoOrderServiceImpl class
 *
 * @author xf107278
 * @date 3/28/2020
 */
@Service
public class WoOrderServiceImpl implements WoOrderService {

    private WoOrderFeignService orderFeignService;

    private IdentityService identityService;

    private IMatImageFeignService iMatImageFeignService;

    private BoxStation boxStation;

    private CutStation cutStation;

    private ExtrusionStation extrusionStation;

    private HangingStation hangingStation;

    private MfgMdApplyUseFeignService mfgMdApplyUseFeignService;

    private UpShelfStation upShelfStation;

    private UpPowderStation upPowderStation;

    private UnShelveWearStripsStation unShelveWearStripsStation;

    private WearStripsStation wearStripsStation;

    private UnShelvePackagingStation unShelvePackagingStation;

    private PackagingStation packagingStation;

    private Map<Integer, StationFactory> stationFactory = new HashMap<>();

    private ISfcService sfcService;

    private MfgProdBatchFeignService mfgProdBatchFeignService;

    private final LcmBoxFillDetailFeignService lcmBoxFillDetailFeignService;

    private final WoOrderLotFeignService woOrderLotFeignService;

    private final IBusinessNumberControllerFeign businessNumberControllerFeign;

    private final WoOperationCompleteDetailFeignService operationCompleteDetailFeignService;
    private final OauthConfig.RequestParams requestParams;

    private final WorkShopPostProcessService workShopPostProcessService;


    public WoOrderServiceImpl(WoOrderFeignService orderFeignService, IdentityService identityService,
                              IMatImageFeignService iMatImageFeignService, BoxStation boxStation,
                              CutStation cutStation, ExtrusionStation extrusionStation, HangingStation hangingStation
            , MfgMdApplyUseFeignService mfgMdApplyUseFeignService, UpShelfStation upShelfStation,
                              UpPowderStation upPowderStation, UnShelveWearStripsStation unShelveWearStripsStation,
                              WearStripsStation wearStripsStation, UnShelvePackagingStation unShelvePackagingStation,
                              PackagingStation packagingStation,
                              ISfcService sfcService, MfgProdBatchFeignService mfgProdBatchFeignService,
                              LcmBoxFillDetailFeignService lcmBoxFillDetailFeignService,
                              WoOrderLotFeignService woOrderLotFeignService,
                              IBusinessNumberControllerFeign businessNumberControllerFeign,
                              WoOperationCompleteDetailFeignService operationCompleteDetailFeignService,
                              OauthConfig.RequestParams requestParams,
                              WorkShopPostProcessService workShopPostProcessService) {
        this.orderFeignService = orderFeignService;
        this.identityService = identityService;
        this.iMatImageFeignService = iMatImageFeignService;
        this.boxStation = boxStation;
        this.cutStation = cutStation;
        this.extrusionStation = extrusionStation;
        this.hangingStation = hangingStation;
        this.mfgMdApplyUseFeignService = mfgMdApplyUseFeignService;
        this.upShelfStation = upShelfStation;
        this.upPowderStation = upPowderStation;
        this.unShelveWearStripsStation = unShelveWearStripsStation;
        this.wearStripsStation = wearStripsStation;
        this.unShelvePackagingStation = unShelvePackagingStation;
        this.packagingStation = packagingStation;
        this.sfcService = sfcService;
        this.mfgProdBatchFeignService = mfgProdBatchFeignService;
        this.lcmBoxFillDetailFeignService = lcmBoxFillDetailFeignService;
        this.woOrderLotFeignService = woOrderLotFeignService;
        this.businessNumberControllerFeign = businessNumberControllerFeign;
        this.operationCompleteDetailFeignService = operationCompleteDetailFeignService;
        this.requestParams = requestParams;
        this.workShopPostProcessService = workShopPostProcessService;

        init();
    }

    private void init() {
        stationFactory.put(StationType.挤压工位, extrusionStation);
        stationFactory.put(StationType.剪切工位, cutStation);
        stationFactory.put(StationType.挂料工位, hangingStation);
        stationFactory.put(StationType.装框工位, boxStation);
        stationFactory.put(StationType.喷涂上架工位, upShelfStation);
        stationFactory.put(StationType.喷涂上粉工位, upPowderStation);
        //stationFactory.put(StationType.穿条下架工位, unShelveWearStripsStation);
        stationFactory.put(StationType.穿条工位, wearStripsStation);
       // stationFactory.put(StationType.包装下架工位, unShelvePackagingStation);
        stationFactory.put(StationType.包装工位, packagingStation);
       // stationFactory.put(StationType.打木箱工位,woodenCaseStation);

    }

    @Override
    public ResponseEntity<Result> getOrderAcInfo(Long orderId, Integer stationType, Principal principal) {
        ResponseEntity<ObjectResult<WoOrder>> objectResultResponseEntity = selectById(orderId);
        WoOrder order = objectResultResponseEntity.getBody().getData();

        Result orderInfo = stationFactory.get(stationType).getOrderInfo(order);
        return ResponseEntity.ok(orderInfo);
    }

    @Override
    public ResponseEntity<Result> addOrder(WoOrder woOrder, Principal principal) {
        woOrder.setId(identityService.getIdentity());
        woOrder.setEnterCode(principal.getName());
        woOrder.setEnterName(principal.getName());
        woOrder.setEnterTime(new Date());
        ResponseEntity<com.diligent.cloud.primary.data.model.Result> insert = orderFeignService.insert(woOrder);
        return ResponseEntity.ok(ConverterUtil.ConverterByResult(insert.getBody()));
    }

    @Override
    public ResponseEntity<ObjectResult<WoOrder>> selectById(Long id) {

        ResponseEntity<com.diligent.cloud.primary.data.model.Result> resultResponseEntity =
                orderFeignService.selectById(Long.valueOf(id));
        ObjectResult<WoOrder> result = new ObjectResult<>((WoOrder) resultResponseEntity.getBody().getData());
        result.modifyCode(resultResponseEntity.getBody().getCode(), resultResponseEntity.getBody().getMsg());
        return ResponseEntity.ok(result);
    }


    @Override
    public ResponseEntity<ListResult> getOrderList(OrderListParams orderListParams) {
        List<OrderInfo> answer = new ArrayList<>();
        List<Condition> conditions = new ArrayList<>();
        PageAndCondition pageAndCondition = new PageAndCondition();
        Condition produceDateCondition = new Condition("produceDate", "eq", orderListParams.getProduceDate(), null);
        Condition machineCodeCondition =  new Condition("machineCode", "eq", orderListParams.getMachineCode(), null);
        Condition orderTypeCondition = new Condition("orderType", "eq", orderListParams.getOrderType(), null);
        Condition orderStatusCondition = new Condition("orderStatus", "in",
                WoOrderStatus.schedulings.getStatus() + "," + WoOrderStatus.inproduction.getStatus(), null);
        Condition systemIdCondition = new Condition("systemId", "eq", orderListParams.getSystemId(), null);

        //TODO 待后续优化
        if (orderListParams.getOrderType() == StationType.挤压工位.intValue()) {

            ListResult result = orderListByExtrusionParams(orderListParams, conditions);
            //查询已加温工单
            if (orderListParams.getUpState()) {
                if (result != null) {
                    return ResponseEntity.ok(result);
                } else {
                    return ResponseEntity.ok(new ListResult(answer));
                }
            }

        } else if (orderListParams.getOrderType() == StationType.剪切工位.intValue() || orderListParams.getOrderType() == StationType.挂料工位.intValue() || orderListParams.getOrderType() == StationType.装框工位.intValue()) {
            return sfcService.getCutOrderList(orderListParams);

        } else if (orderListParams.getOrderType() == StationType.喷涂上架工位.intValue() || orderListParams.getOrderType() == StationType.喷涂上粉工位.intValue()) {

            orderTypeCondition = new Condition("orderType", "eq", OrderType.表面处理工单, null);
            conditions.add(new Condition("colorGroupCode", "orderBy", "null", null));
        } else if (orderListParams.getOrderType() == StationType.穿条下架工位.intValue() || orderListParams.getOrderType() == StationType.穿条工位.intValue()) {
            orderTypeCondition = new Condition("orderType", "eq", OrderType.后加工工单, null);
            conditions.add(new Condition("parentId", "nn", 0, null));

        } else if (orderListParams.getOrderType() == StationType.包装下架工位.intValue() || orderListParams.getOrderType() == StationType.包装工位.intValue()) {

            orderTypeCondition = new Condition("orderType", "eq", OrderType.包装工单, null);

        }

        conditions.add(produceDateCondition);
        conditions.add(machineCodeCondition);
        conditions.add(orderTypeCondition);
        conditions.add(orderStatusCondition);
        conditions.add(systemIdCondition);

        Pagination pagination = new Pagination(orderListParams.getPageIndex(), orderListParams.getPageSize());
        pageAndCondition.setPagination(pagination);
        pageAndCondition.setConditions(conditions);
        ResponseEntity<com.diligent.cloud.primary.data.model.Result<IPage<WoOrder>>> page =
                orderFeignService.page(pageAndCondition);

        for (WoOrder order : page.getBody().getData().getRecords()) {
            OrderInfo orderInfo = new OrderInfo();
            BeanUtils.copyProperties(order, orderInfo);

//            String matCode = sfcService.getMatCodeByOrderIdAndSystemId(order.getId(),
//                    order.getSystemId(), MatType.模具);
            conditions = new ArrayList<>();
            conditions.add(new Condition("matCodeCv", "eq", order.getMatCode(), null));
            conditions.add(new Condition("systemId", "eq", order.getSystemId(), null));
            conditions.add(new Condition("machCode", "eq", order.getMachineCode(), null));
            ResponseEntity<com.diligent.cloud.primary.data.model.Result> mdApplyUserResource =
                    mfgMdApplyUseFeignService.selectDataByCondition(conditions);

            List<LinkedHashMap> mdApplyUsers = (List<LinkedHashMap>) mdApplyUserResource.getBody().getData();
            orderInfo.setMdNumber(mdApplyUsers.size());

            if (!(orderListParams.getOrderType() == StationType.喷涂上架工位.intValue() || orderListParams.getOrderType() == StationType.喷涂上粉工位.intValue() || orderListParams.getOrderType() == StationType.穿条下架工位.intValue() || orderListParams.getOrderType() == StationType.穿条工位.intValue())) {
                ResponseEntity<com.diligent.cloud.primary.data.model.Result> mouldPic =
                        iMatImageFeignService.getMouldPic(order.getMatCode());

                if (mouldPic.getBody().getCode() == 0) {
                    orderInfo.setImg((String) mouldPic.getBody().getData());
                }
            }
            answer.add(orderInfo);
        }

        ListResult result = new ListResult(answer);

        if (page.getBody().getData().getRecords().size() != 0) {
            result.modifyCode(page.getBody().getCode(),
                    page.getBody().getData().getTotal().toString());
        } else {
            result.modifyCode(page.getBody().getCode(),
                    "0");
        }

        return ResponseEntity.ok(result);
    }

    /**
     * 工单结束
     *
     * @param orderAction
     * @param woOrderId
     * @param principal
     * @return
     */
    @Override
    @Transactional
    public ResponseEntity<Result> updateOrderStatus(Integer orderAction, Long woOrderId, Long asId,
                                                    Principal principal) {

        ResponseEntity<com.diligent.cloud.primary.data.model.Result> orderResult =
                orderFeignService.selectById(woOrderId);
        Preconditions.checkNotNull(orderResult.getBody().getData(), "此查询不到此[%s]工单", woOrderId);
        WoOrder order = (WoOrder) orderResult.getBody().getData();
        if (WoOrderStatus.finish.getStatus().equals(order.getOrderStatus())){
            ObjectResult result = new ObjectResult();
            result.modifyCode(Codes.fail.getCode(),"此工单已完工");
            return ResponseEntity.ok(result);
        }
        order.setOrderStatus(orderAction);

        //更新工单位已完成状态
        ResponseEntity<com.diligent.cloud.primary.data.model.Result> updateOrderResult =
                orderFeignService.update(order);

        //工单结束更新工序完工结束时间
        WoOperationCompleteDetail operationCompleteDetail = new WoOperationCompleteDetail();
        operationCompleteDetail.setEndTime(new Date());
        operationCompleteDetail.setModifyCode(principal.getName());
        operationCompleteDetail.setModifyName(principal.getName());
        operationCompleteDetail.setModifyTime(new Date());
        Condition condition = new Condition("woOrder", "eq", order.getWoOrder(), null);
        List<Condition> conditions = new ArrayList<>();
        conditions.add(condition);
        operationCompleteDetail.setConditions(conditions);

         operationCompleteDetailFeignService.updateByCondition(operationCompleteDetail);

        JSONObject jsonObject = (JSONObject) JSONObject.toJSON(updateOrderResult.getBody().getData());

        return ResponseEntity.ok(ConverterUtil.ConverterByData(jsonObject
                , updateOrderResult.getBody().getCode()
                , updateOrderResult.getBody().getMsg()));
    }


    @Override
    public ResponseEntity<ListResult> getSameOrderByProdBatch(String prodBatch, String machCode, Long systemId,
                                                              Integer orderType, Integer isFinished,
                                                              Integer operationIsFinished) {
        return sfcService.getSameOrderByProdBatch(prodBatch, machCode, systemId, orderType, isFinished,
                operationIsFinished);
    }

    @Override
    @Transactional
    @LcnTransaction
    public ResponseEntity<ObjectResult> addWoOrderLots(String boxCode, Long systemId, Principal principal) {
        PageAndCondition pageAndCondition = new PageAndCondition();
        Pagination pagination = new Pagination(1L, 100000L);
        Condition condition = new Condition("refBoxCode", "eq", boxCode, null);
        List<Condition> conditions = new ArrayList<>();
        conditions.add(condition);
        pageAndCondition.setPagination(pagination);
        pageAndCondition.setConditions(conditions);
        String lotCode = businessNumberControllerFeign.nextId(systemId, 1L, "lot", "sfc", new HashMap()).getBody();

        ResponseEntity<com.diligent.cloud.primary.data.model.Result<IPage<LcmBoxFillDetail>>> resultResponseEntity =
                lcmBoxFillDetailFeignService.page(pageAndCondition);
        List<LcmBoxFillDetail> lcmBoxFillDetails = resultResponseEntity.getBody().getData().getRecords();
        for (LcmBoxFillDetail lcmBoxFillDetail : lcmBoxFillDetails) {
            Preconditions.checkNotNull(lcmBoxFillDetail.getRefWoOrder(), "工单号为null");
            Long woOrderId = Long.parseLong(lcmBoxFillDetail.getRefWoOrder());
            WoOrderLot woOrderLot = new WoOrderLot();
            woOrderLot.setWoOrderId(woOrderId);
            woOrderLot.setLotCode(lotCode);
            woOrderLot.setSystemId(systemId);
            woOrderLot.setEnterCode(principal.getName());
            woOrderLot.setCompanyId(requestParams.getCompanyId());
            woOrderLot.setSystemId(requestParams.getSystemId());
            woOrderLotFeignService.insert(woOrderLot);
        }
        ObjectResult objectResult = new ObjectResult();
        objectResult.modifyCode(Codes.success.getCode(), Codes.success.getMsg());
        return ResponseEntity.ok(objectResult);
    }

    @Override
    public ResponseEntity<Result> updateOrderStatus(Long orderId, Long mdId,Long asId, String prodBatch,
                                                    Principal principal) {
        ResponseEntity<com.diligent.cloud.primary.data.model.Result> woOrderResponse =
                orderFeignService.selectById(orderId);
        Preconditions.checkNotNull(woOrderResponse.getBody().getData(), "查询不到id为[%s]的工单", orderId);

        WoOrder order = (WoOrder) woOrderResponse.getBody().getData();
        PageAndCondition pageAndCondition = new PageAndCondition();
        List<Condition> conditions = new ArrayList<>();


        conditions.add(new Condition("woOrder", "eq", order.getWoOrder(), null));
        conditions.add(new Condition("endTime", "nn", 1, null));
        pageAndCondition.setPagination(new Pagination(1L, 1L));
        pageAndCondition.setConditions(conditions);
        int size = operationCompleteDetailFeignService.page(pageAndCondition).getBody().getData().getRecords().size();
        if (size > 0) {
            ObjectResult objectResult = new ObjectResult();
            objectResult.modifyCode(Codes.fail.getCode(), "工单已结束!");
            return ResponseEntity.ok(objectResult);
        }

        if (OrderType.表面处理工单.equals(order.getOrderType())) {
            order.setCv6("已上架");
        }

        order.setModifyCode(principal.getName());
        order.setModifyName(principal.getName());
        order.setModifyTime(new Date());
        order.setOrderStatus(WoOrderStatus.inproduction.getStatus());
        ResponseEntity<com.diligent.cloud.primary.data.model.Result> update = orderFeignService.update(
                order);

        pageAndCondition.setPagination(new Pagination(1L, 1L));
        conditions = new ArrayList<>();
        conditions.add(new Condition("woOrder", "eq", order.getWoOrder(), null));
        pageAndCondition.setConditions(conditions);
        ResponseEntity<com.diligent.cloud.primary.data.model.Result<IPage<WoOperationCompleteDetail>>> operationCompleteDetailPage =
                operationCompleteDetailFeignService.page(pageAndCondition);
        if (operationCompleteDetailPage.getBody().getData().getRecords().size() != 0) {
            WoOperationCompleteDetail operationCompleteDetail =
                    operationCompleteDetailPage.getBody().getData().getRecords().stream().findFirst().get();
            operationCompleteDetail.setStartTime(new Date());
            if (operationCompleteDetail.getUsrTxt1()==null){
                operationCompleteDetail.setUsrTxt1(asId.toString());
            }
            operationCompleteDetailFeignService.update(operationCompleteDetail);
        }else{
            ResponseEntity<com.diligent.cloud.primary.data.model.Result<MfgProdBatch>> byBatchLast =
                    mfgProdBatchFeignService.getByBatchLast(order.getMachineCode(), order.getSystemId());
            Preconditions.checkNotNull(byBatchLast.getBody().getData(),"查询不到批次");
             sfcService.addOperationComplete(order,
                    byBatchLast.getBody().getData().getProdBatch(), asId,true, principal);

        }

        return ResponseEntity.ok(ConverterUtil.ConverterByResult(update.getBody()));
    }

    @Override
    public ResponseEntity<com.diligent.cloud.primary.data.model.Result> getWoOrderProgress(WoOrderProgressParams orderProgressParams) {
        return orderFeignService.getWoOrderProgress(orderProgressParams);
    }

    @Override
    public ResponseEntity<com.diligent.cloud.primary.data.model.Result> updateOrderDocStatus(String action,
                                                                                             WoOrder woOrder,
                                                                                             Principal principal) {
        return orderFeignService.updateDocStatus(action, woOrder);
    }


    private ListResult orderListByExtrusionParams(OrderListParams orderListParams,
                                                  List<Condition> conditions) {
        PageAndCondition pageAndCondition = new PageAndCondition();

        if (orderListParams.getMatCode() != null) {
            Condition matCodeCondition = new Condition("matCode", "eq", orderListParams.getMatCode(), null);
            conditions.add(matCodeCondition);
        }
        if (orderListParams.getUpState()) {
            //找加温摸具
            List<Condition> conditionList = new ArrayList<>();
            conditionList.add(new Condition("docStatus", "eq",
                    MatStatus.processing.getStatus(),
                    null));
            conditionList.add(new Condition("machCode", "eq", orderListParams.getMachineCode(), null));
            conditionList.add(new Condition("systemId", "eq", orderListParams.getSystemId(), null));


            pageAndCondition.setConditions(conditionList);
            pageAndCondition.setPagination(new Pagination(1L, 1L));
            ResponseEntity<com.diligent.cloud.primary.data.model.Result<IPage<MfgMdApplyUse>>> mfgMdApplyUseResponseEntity =
                    mfgMdApplyUseFeignService.selectDataByConditionPage(pageAndCondition);
            if (mfgMdApplyUseResponseEntity.getBody().getData().getRecords().size() != 0) {
                for (MfgMdApplyUse mfgMdApplyUse : mfgMdApplyUseResponseEntity.getBody().getData().getRecords()) {
                    conditionList = new ArrayList<>();
                    conditionList.add(new Condition("orderType", "eq", StationType.挤压工位, null));
                    conditionList.add(new Condition("matCode", "eq", mfgMdApplyUse.getMatCodeCv(), null));
                    conditionList.add(new Condition("machineCode", "eq", orderListParams.getMachineCode(), null));
                    conditionList.add(new Condition("orderStatus", "eq",
                            WoOrderStatus.schedulings.getStatus(), null));

                    pageAndCondition.setConditions(conditionList);
                    ResponseEntity<com.diligent.cloud.primary.data.model.Result<IPage<WoOrder>>> orderPage =
                            orderFeignService.page(pageAndCondition);
                if (orderPage.getBody().getData().getRecords().size()==0){continue;}
                    ListResult result =
                            new ListResult(Collections.singletonList(orderPage.getBody().getData().getRecords().stream().findFirst().get()));
                    result.modifyCode(orderPage.getBody().getCode(),
                            orderPage.getBody().getData().getTotal().toString());
                    return result;
                }
            }
        }
        return null;
    }


}


